package com.psbc.redislock.aspectj;

import com.psbc.redislock.annotation.RedisLock;
import com.psbc.redislock.exception.RedisLockException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class RedisLockAspect {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 环绕通知 ：切断表达式，找到有RedisLock注解的地方
     * @param pjp
     * @param redisLock
     * @return
     */
    @Around("@annotation(redisLock)")
    public Object applyLock(ProceedingJoinPoint pjp, RedisLock redisLock) {
        //获取key值
        String key = redisLock.key();
        com.psbc.redislock.lock.redis.RedisLock lock = new com.psbc.redislock.lock.redis.RedisLock(redisTemplate, key);
        boolean acquiredLock = false;
        try {
            //获取锁
            acquiredLock = lock.acquireLock();
            if (acquiredLock) {
                //跑加锁的方法
                return pjp.proceed();
            } else {
                throw new RedisLockException("加锁失败: " + key);
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        } finally {
            if (acquiredLock) {
                //释放锁
                lock.releaseLock();
            }
        }
        return null;
    }
}
